<!doctype html>
<html lang="en">
<head><meta name="generator" content="Hexo 3.9.0">
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>言成言成啊</title>
    <link rel="shortcut icon" href="/images/favicon.ico">
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/meethigher/cdn@9.0/css/meethigher-font.css">
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/meethigher/cdn@9.0/css/animate.css">
    <link rel="stylesheet" href="/css/index.css">
</head>
<body>
<header class="header">
    <div class="header-menu"><span class="fa fa-bars"></span></div>
    <div class="header-search"><span class="fa fa-search"></span></div>
    <div class="header-title"><a href="/">言成言成啊 | <span class="header-subtitle">Kit Chen&#39;s Blog</span></a></div>
    <ul class="header-navbar clearFix">
        
            <li><a href="/">主页</a></li>
        
            <li><a href="/tags">标签</a></li>
        
            <li><a href="/archives">归档</a></li>
        
            <li><a href="/search">导航</a></li>
        
    </ul>
</header>
<main class="main">
    <div class="main-content meethigher-scroll">
    <article class="post">
        <div class="post-title">
            <h2 class="title">线程</h2>
        </div>
        <div class="post-media2">
            <span class="post-time">2019-10-25</span>
            
                <ul class="article-tag-list"><li class="article-tag-list-item"><a class="article-tag-list-link" href="/tags/java/">java</a></li></ul>
            
        </div>
        <div class="post-content blog-markdown">
            <h1 id="第一章-多线程"><a href="#第一章-多线程" class="headerlink" title="第一章 多线程"></a>第一章 多线程</h1><p>我们在之前，学习的程序在没有跳转语句的前提下，都是由上至下依次执行，那现在想要设计一个程序，边打游戏边听歌，怎么设计？</p>
<p>要解决上述问题,咱们得使用多进程或者多线程来解决.</p>
<h2 id="1-1-并发与并行"><a href="#1-1-并发与并行" class="headerlink" title="1.1 并发与并行"></a>1.1 并发与并行</h2><ul>
<li><strong>并发</strong>：指两个或多个事件在<strong>同一个时间段内</strong>发生。交替执行，就相当于一个人吃俩馒头，这个吃一口，那个吃一口，效率低。</li>
<li><strong>并行</strong>：指两个或多个事件在<strong>同一时刻</strong>发生。同时执行，两个人吃两个馒头，效率低。</li>
</ul>
<img src="/2019/10/25/thread/并行与并发.bmp" title="并行与并发">

<p>在操作系统中，安装了多个程序，并发指的是在一段时间内宏观上有多个程序同时运行，这在单 CPU 系统中，每一时刻只能有一道程序执行，即微观上这些程序是分时的交替运行，只不过是给人的感觉是同时运行，那是因为分时交替运行的时间是非常短的。</p>
<p>而在多个 CPU 系统中，则这些可以并发执行的程序便可以分配到多个处理器上（CPU），实现多任务并行执行，即利用每个处理器来处理一个可以并发执行的程序，这样多个程序便可以同时执行。目前电脑市场上说的多核 CPU，便是多核处理器，核 越多，并行处理的程序越多，能大大的提高电脑运行的效率。</p>
<blockquote>
<p>注意：单核处理器的计算机肯定是不能并行的处理多个任务的，只能是多个任务在单个CPU上并发运行。同理,线程也是一样的，从宏观角度上理解线程是并行运行的，但是从微观角度上分析却是串行运行的，即一个线程一个线程的去运行，当系统只有一个CPU时，线程会以某种顺序执行多个线程，我们把这种情况称之为线程调度。</p>
</blockquote>
<h2 id="1-2-线程与进程"><a href="#1-2-线程与进程" class="headerlink" title="1.2 线程与进程"></a>1.2 线程与进程</h2><p>介绍进程与线程之前，先来介绍一下cpu。</p>
<p>cpu：中央处理器，对数据进行计算，指挥电脑中的软件和硬件干活</p>
<p>cpu分类：</p>
<ul>
<li>AMD</li>
<li>Intel：见博客intel命名规则</li>
</ul>
<p>进程与线程：</p>
<ul>
<li><p><strong>进程</strong>：是指一个内存中运行的应用程序，每个进程都有一个独立的内存空间，一个应用程序可以同时运行多个进程；进程也是程序的一次执行过程，是系统运行程序的基本单位；系统运行一个程序即是一个进程从创建、运行到消亡的过程。</p>
</li>
<li><p><strong>线程</strong>：线程是进程中的一个执行单元，负责当前进程中程序的执行，一个进程中至少有一个线程。一个进程中是可以有多个线程的，这个应用程序也可以称之为多线程程序。 </p>
<p>简而言之：一个程序运行后至少有一个进程，一个进程中可以包含多个线程 </p>
</li>
</ul>
<p>我们可以再电脑底部任务栏，右键—–&gt;打开任务管理器,可以查看当前任务的进程：</p>
<p><strong>进程</strong></p>
<img src="/2019/10/25/thread/进程概念.png" title="进程概念">

<p><strong>线程</strong></p>
<img src="/2019/10/25/thread/线程概念.png" title="线程概念">

<p><strong>线程调度:</strong></p>
<ul>
<li><p>分时调度</p>
<p>所有线程轮流使用 CPU 的使用权，平均分配每个线程占用 CPU 的时间。</p>
</li>
<li><p>抢占式调度</p>
<p>优先让优先级高的线程使用 CPU，如果线程的优先级相同，那么会随机选择一个(线程随机性)，<strong>Java使用的为抢占式调度。</strong></p>
<ul>
<li><p>设置线程的优先级</p>
<img src="/2019/10/25/thread/设置线程优先级.bmp" title="设置线程优先级">
</li>
<li><p>抢占式调度详解</p>
<p>大部分操作系统都支持多进程并发运行，现在的操作系统几乎都支持同时运行多个程序。比如：现在我们上课一边使用编辑器，一边使用录屏软件，同时还开着画图板，dos窗口等软件。此时，这些程序是在同时运行，”感觉这些软件好像在同一时刻运行着“。</p>
<p>实际上，CPU(中央处理器)使用抢占式调度模式在多个线程间进行着高速的切换。对于CPU的一个核而言，某个时刻，只能执行一个线程，而 CPU的在多个线程间切换速度相对我们的感觉要快，看上去就是在同一时刻运行。<br>其实，多线程程序并不能提高程序的运行速度，但能够提高程序运行效率，让CPU的使用率更高。</p>
<img src="/2019/10/25/thread/抢占式调度.bmp" title="抢占式调度">

</li>
</ul>
</li>
</ul>
<h2 id="1-3-利用Thread类的子类创建线程"><a href="#1-3-利用Thread类的子类创建线程" class="headerlink" title="1.3 利用Thread类的子类创建线程"></a>1.3 利用Thread类的子类创建线程</h2><p>Java使用<code>java.lang.Thread</code>类代表<strong>线程</strong>，所有的线程对象都必须是Thread类或其子类的实例。每个线程的作用是完成一定的任务，实际上就是执行一段程序流即一段顺序执行的代码。Java使用线程执行体来代表这段程序流。Java中通过继承Thread类来<strong>创建</strong>并<strong>启动多线程</strong>的步骤如下：</p>
<ol>
<li>定义Thread类的子类，并重写该类的run()方法，该run()方法的方法体就代表了线程需要完成的任务,因此把run()方法称为线程执行体。</li>
<li>创建Thread子类的实例，即创建了线程对象</li>
<li>调用线程对象的start()方法来启动该线程</li>
</ol>
<p>多线程原理-随机打印结果</p>
<img src="/2019/10/25/thread/多线程原理.png" title="多线程原理">

<p>程序启动运行main时候，java虚拟机启动一个进程，主线程main在main()调用时候被创建。随着调用mt的对象的start方法，另外一个新的线程也就启动了，这样，整个线程就在多线程下运行。</p>
<p>通过这张图我们可以很清晰的看到多线程的执行流程，那么为什么可以完成并发执行（多核下可以并行执行，单核只能并发执行）呢？</p>
<p>多线程执行是，在栈内存中，其实每一个执行线程都有一片自己所属的栈内存空间。进行方法的压栈和弹栈。</p>
<p>多线程原理-内存图解</p>
<img src="/2019/10/25/thread/栈内存原理图.png" title="栈内存原理图">

<p>当执行线程的任务结束了，线程自动在栈内存中释放了。但是当所有的执行线程都结束了，那么线程也就结束了。</p>
<p>代码如下：</p>
<p>测试类：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Demo01</span> </span>&#123;</span><br><span class="line">	<span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">		<span class="comment">//创建自定义线程对象</span></span><br><span class="line">		MyThread mt = <span class="keyword">new</span> MyThread(<span class="string">"新的线程！"</span>);</span><br><span class="line">		<span class="comment">//开启新线程</span></span><br><span class="line">		mt.start();</span><br><span class="line">		<span class="comment">//在主方法中执行for循环</span></span><br><span class="line">		<span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">0</span>; i &lt; <span class="number">10</span>; i++) &#123;</span><br><span class="line">			System.out.println(<span class="string">"main线程！"</span>+i);</span><br><span class="line">		&#125;</span><br><span class="line">	&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>自定义线程类：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">MyThread</span> <span class="keyword">extends</span> <span class="title">Thread</span> </span>&#123;</span><br><span class="line">	<span class="comment">//定义指定线程名称的构造方法</span></span><br><span class="line">	<span class="function"><span class="keyword">public</span> <span class="title">MyThread</span><span class="params">(String name)</span> </span>&#123;</span><br><span class="line">		<span class="comment">//调用父类的String参数的构造方法，指定线程的名称</span></span><br><span class="line">		<span class="keyword">super</span>(name);</span><br><span class="line">	&#125;</span><br><span class="line">	<span class="comment">/**</span></span><br><span class="line"><span class="comment">	 * 重写run方法，完成该线程执行的逻辑</span></span><br><span class="line"><span class="comment">	 */</span></span><br><span class="line">	<span class="meta">@Override</span></span><br><span class="line">	<span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">run</span><span class="params">()</span> </span>&#123;</span><br><span class="line">		<span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">0</span>; i &lt; <span class="number">10</span>; i++) &#123;</span><br><span class="line">			System.out.println(getName()+<span class="string">"：正在执行！"</span>+i);</span><br><span class="line">		&#125;</span><br><span class="line">	&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h2 id="1-4-利用Runnable接口对象创建线程"><a href="#1-4-利用Runnable接口对象创建线程" class="headerlink" title="1.4 利用Runnable接口对象创建线程"></a>1.4 利用Runnable接口对象创建线程</h2><h2 id="1-5-Thread和Runnable的区别"><a href="#1-5-Thread和Runnable的区别" class="headerlink" title="1.5 Thread和Runnable的区别"></a>1.5 Thread和Runnable的区别</h2><h2 id="1-6-匿名内部类方式实现线程的创建"><a href="#1-6-匿名内部类方式实现线程的创建" class="headerlink" title="1.6 匿名内部类方式实现线程的创建"></a>1.6 匿名内部类方式实现线程的创建</h2><h1 id="第二章-线程安全"><a href="#第二章-线程安全" class="headerlink" title="第二章 线程安全"></a>第二章 线程安全</h1><h2 id="2-1-线程安全"><a href="#2-1-线程安全" class="headerlink" title="2.1 线程安全"></a>2.1 线程安全</h2><h2 id="2-2-线程同步"><a href="#2-2-线程同步" class="headerlink" title="2.2 线程同步"></a>2.2 线程同步</h2><h2 id="2-3-同步代码块"><a href="#2-3-同步代码块" class="headerlink" title="2.3 同步代码块"></a>2.3 同步代码块</h2><h2 id="2-4-同步方法"><a href="#2-4-同步方法" class="headerlink" title="2.4 同步方法"></a>2.4 同步方法</h2><h2 id="2-5-Lock锁"><a href="#2-5-Lock锁" class="headerlink" title="2.5 Lock锁"></a>2.5 Lock锁</h2><h1 id="第三章-线程状态"><a href="#第三章-线程状态" class="headerlink" title="第三章 线程状态"></a>第三章 线程状态</h1><h2 id="3-1-线程状态概述"><a href="#3-1-线程状态概述" class="headerlink" title="3.1 线程状态概述"></a>3.1 线程状态概述</h2><h2 id="3-2-Timed-Waiting（计时等待）"><a href="#3-2-Timed-Waiting（计时等待）" class="headerlink" title="3.2 Timed Waiting（计时等待）"></a>3.2 Timed Waiting（计时等待）</h2><h2 id="3-3-BLOCKED（锁阻塞）"><a href="#3-3-BLOCKED（锁阻塞）" class="headerlink" title="3.3 BLOCKED（锁阻塞）"></a>3.3 BLOCKED（锁阻塞）</h2><h2 id="3-4-Waiting（无限等待）"><a href="#3-4-Waiting（无限等待）" class="headerlink" title="3.4 Waiting（无限等待）"></a>3.4 Waiting（无限等待）</h2><h2 id="3-5-补充知识点"><a href="#3-5-补充知识点" class="headerlink" title="3.5 补充知识点"></a>3.5 补充知识点</h2>
        </div>
        
            <div class="busuanzi">
                <span id="busuanzi_container_page_pv">阅读量<span id="busuanzi_value_page_pv"></span>次</span>
                <script async src="//busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js"></script>
            </div>
        
    </article>
</div>
    <pointer href="javascript:void(0);" class="arrow fa fa-arrow-up"></pointer>
<pointer href="javascript:void(0);" class="arrow fa fa-arrow-down"></pointer>

</main>
<aside class="aside">
    <div class="aside-content">
        <div class="aside-avatar"><img src="/images/kitchen.jpg" alt="言成"></div>
        <div class="aside-author">言成</div>
        <div class="aside-description">爱学习，爱运动，爱看妹子</div>
        <ul class="aside-contact clearFix">
            <li><span class="fa fa-github"></span><a href="https://github.com/meethigher">Github</a></li>
            <li><span class="fa fa-envelope"></span><a href="javascript:void(0);">meethigher@qq.com</a></li>
            <li><span class="fa fa-weixin"></span><a href="javascript:void(0);"><img src="/images/weixin.png" alt="扫描微信二维码，加我哦！"></a></li>
        </ul>
    </div>
</aside>
<div class="toolbar"><span class="fa fa-th"></span></div>
<div id="particles-js"></div>
<script src="https://cdn.jsdelivr.net/gh/meethigher/cdn@9.0/js/jquery.min.js"></script>
<script src="https://cdn.jsdelivr.net/gh/meethigher/cdn@9.0/js/particles.min.js"></script>
<script src="https://cdn.jsdelivr.net/gh/meethigher/cdn@9.0/js/app.js"></script>
<script src="/js/meethigher.js"></script>
<script src="/js/toolbar.js"></script>
</body>
</html>